﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using INIFILE;

namespace CameraCapture
{
    class SerialPortDataController
    {
        SerialPort sp1;
        System.Threading.Timer timerThr;

        public static int timeout ; //彩票从1号灯滚动到2号灯 和 进入2号灯到出2号灯 超时时间ms
        public static int cameradelay ;//磁铁完全压下抬起耗时 ms
        //public static int cameraClosedelay ;//工作完成没新任务超时 自动关闭摄像头

        public static State state;

        public SerialPortDataController(SerialPort sp)
        {
            timeout = Convert.ToInt32(Profile.G_Timeout) ;
            cameradelay = Convert.ToInt32(Profile.G_CameraDelay);
            sp.DataReceived += new SerialDataReceivedEventHandler(sp1_DataReceived);
            initPort(sp);
            timerThr = new System.Threading.Timer(new TimerCallback(StateTimeout),null, Timeout.Infinite, timeout);
        }

        /// <summary>
        /// 压紧后拍照事件
        /// </summary>
        public event Action<int> CameraDelayEvent;
        protected virtual void OnDelayCaptureEvent(int cameradelay)
        {
            if (CameraDelayEvent != null)
            {
                CameraDelayEvent(cameradelay);
            }
        }

        /// <summary>
        /// 超时触发状态事件
        /// </summary>
        public event Action<State> StateEvent;
        protected virtual void OnStateEvent(State state)
        {
            if (StateEvent != null)
            {
                StateEvent(state);
            }
        }

        /// <summary>
        /// 打开摄像头事件
        /// </summary>
        public event Action CameraConenctEvent;
        protected virtual void OnCameraConenctEvent()
        {
            if (CameraConenctEvent != null)
            {
                CameraConenctEvent();
            }
        }


        /// <summary>
        /// 发送数据事件
        /// </summary>
        public event Action<Byte[]> SendDataEvent;
        protected virtual void OnSendDataEvent(Byte[] senddata)
        {
            if (SendDataEvent != null)
            {
                SendDataEvent(senddata);
            }
        }

        /// <summary>
        /// 接收数据事件
        /// </summary>
        public event Action<Byte[]> RecvDataEvent;
        protected virtual void OnRecvDataEvent(Byte[] recvdata)
        {
            if (RecvDataEvent != null)
            {
                RecvDataEvent(recvdata);
            }
        }

        /// <summary>
        /// 接收数据事件
        /// </summary>
        public event Action<State> lightDataEvent;
        protected virtual void OnlightDataEvent(State state)
        {
            if (lightDataEvent != null)
            {
                lightDataEvent(state);
            }
        }


        public bool islotteryin1_2 = false; //彩票在1 2 号红外线中间位置
        /// <summary>
        /// 发送字节数据
        /// </summary>
        /// <param name="sendbytes"></param>
        public void Send(Byte[] sendbytes)
        {
            if (sp1.IsOpen)
            {
                sp1.Write(sendbytes, 0, sendbytes.Length);
                OnSendDataEvent(sendbytes);
            }
        }

        /// <summary>
        /// 延时发送关闭指令
        /// </summary>
        /// <param name="delay"></param>
        private void DelaySendStopInstruction(int delay)
        {
            Thread delayStopThread = new Thread(new ThreadStart(() =>
            {
                System.Threading.Thread.Sleep(delay);
                Send(Instruction.stop_instruction);
            }));
            delayStopThread.IsBackground = true;
            delayStopThread.Start();
        }

        private void StateTimeout(object value)
        {
            OnStateEvent(state);
        }

        public void initPort(SerialPort sp)
        {
            //准备就绪      
            this.sp1 = sp;
            sp1.DtrEnable = true;
            sp1.RtsEnable = true;
            //设置数据读取超时为1秒
            sp1.ReadTimeout = 1000;
            sp1.PortName = Profile.G_PORTNAME;
            sp1.BaudRate = Convert.ToInt32(Profile.G_BAUDRATE);
            sp1.DataBits = Convert.ToInt32(Profile.G_DATABITS);

            switch (Profile.G_STOP)
            {
                case "1":
                    sp1.StopBits = StopBits.One;
                    break;
                case "1.5":
                    sp1.StopBits = StopBits.OnePointFive;
                    break;
                case "2":
                    sp1.StopBits = StopBits.Two;
                    break;
                default:
                    System.Windows.Forms.MessageBox.Show("Error：停止位参数非法!", "Error");
                    break;
            }
            switch (Profile.G_PARITY)             //校验位
            {
                case "NONE":
                    sp1.Parity = Parity.None;
                    break;
                case "Odd":
                    sp1.Parity = Parity.Odd;
                    break;
                case "Even":
                    sp1.Parity = Parity.Even;
                    break;
                default:
                    System.Windows.Forms.MessageBox.Show("Error：校验位参数非法!", "Error");
                    break;
            }
        }

        int lastbitlight = 0;

        /// <summary>
        /// 拍照后停止
        /// </summary>
        public bool bStop = true;

        /// <summary>
        /// 检测到2号灯从没阻挡后 到接收到阻挡命令才能拍照
        /// </summary>
        public bool bCaptured= false;

        private void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                Byte[] receivedData = new Byte[sp1.BytesToRead];        //创建接收字节数组

                {
                    sp1.Read(receivedData, 0, receivedData.Length);         //读取数据
                    
                    Byte chk = 0;
                    for (int i = 0; i < receivedData.Length - 1; i++)
                    {
                        chk += receivedData[i];
                    }
                    if (receivedData.Length==4&&receivedData[0].Equals(0xAA) && receivedData[1].Equals(0xAA) && receivedData[3].Equals(chk))
                    {
                        //接收数据格式 例如1号灯亮 AAAA0155
                        Byte light_bit = receivedData[2];
                        int bitlight = 0x07 & light_bit;


                        if (lastbitlight != bitlight)
                        {
                            lastbitlight = bitlight;
                            OnRecvDataEvent(receivedData);
                            switch (bitlight)
                            {
                                case 0x00://1,2号灯没阻挡
                                    state = State.Sleep;
                                    if (!islotteryin1_2)
                                    {
                                        //Send(Instruction.stop_instruction);
                                        DelaySendStopInstruction(2000);
                                    }
                                    bCaptured = false;
                                    OnlightDataEvent(State.Sleep);
                                    //timerThr.Change(cameraClosedelay, Timeout.Infinite);
                                    break;
                                case 0x01://1号灯检测到阻挡
                                    timerThr.Change(timeout, Timeout.Infinite);
                                    state = State.Lock1;
                                    Send(Instruction.startscroll_instruction);
                                    OnCameraConenctEvent();
                                    OnlightDataEvent(State.Lock1);
                                    islotteryin1_2 = true;
                                    bCaptured = false;
                                    break;
                                case 0x02://2号灯检测到阻挡
                                    if (islotteryin1_2)
                                    {
                                        if (!bCaptured)
                                        {
                                            islotteryin1_2 = false;
                                            timerThr.Change(timeout, Timeout.Infinite);
                                            state = State.Lock2;
                                            OnDelayCaptureEvent(cameradelay);
                                            OnlightDataEvent(State.Lock2);
                                            bCaptured = true;
                                        }
                                    }
                                    break;
                                case 0x03://1,2号灯都阻挡 按照1号灯阻挡处理
                                    islotteryin1_2 = true;
                                    timerThr.Change(timeout, Timeout.Infinite);
                                    state = State.Lock1;
                                    Send(Instruction.startscroll_instruction);
                                    OnCameraConenctEvent();
                                    OnlightDataEvent(State.Lock1);
                                    break;
                                case 0x04://(第3个灯 已过时)
                                    Send(Instruction.stop_instruction);
                                    timerThr.Change(timeout, Timeout.Infinite);
                                    break;
                                case 0x05:

                                    break;
                                case 0x06:

                                    break;
                                case 0x07:

                                    break;
                                default:
                                    state = State.Unknown;
                                    break;
                            }
                        }

                    }
                }
            }
            catch (System.Exception ex)
            {
                //OnStateEvent(state);
                Console.WriteLine(ex.Message);
            }
        }
    }
}
